﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace WindowsFormsApplication2
{
   public class KeyboardHookLib
    {
        private const int WH_KEYBOARD_LL = 13;//键盘
        //键盘处理事件委托
        private delegate int HookHandle(int nCode,int wParam,IntPtr IParam);
        //客户端键盘处理事件
        public delegate void ProcessKeyHandle(HookStruct param, out bool handle);
        //接收SetWindowsHookEx返回值
        private static int _hHookValue = 0;
        //钩子程序处理事件
        private HookHandle _keyBoardHookProcedure;

        //Hook结构
        [StructLayout(LayoutKind.Sequential)]
        public class HookStruct
        {
            public int vkCode;
            public int scanCode;
            public int flags;
            public int time;
            public int dwExtraInfo;
        }

        //设置钩子
        [DllImport("user32.dll")]
        private static extern int SetWindowsHookEx(int idHook, HookHandle lpfn, IntPtr hInstance, int threadId);

        //取消钩子
        [DllImport("user32.dll",CharSet =CharSet.Auto,CallingConvention =CallingConvention.StdCall)]
        private static extern bool UnhookWindowsHookEx(int idHook);

        //调用下一个钩子
        [DllImport("user32.dll")]
        private static extern int CallNextHookEx(int idHook,int nCode,int wParam,IntPtr IParam);

        //获取当前线程
        [DllImport("kernel32.dll")]
        private static extern int GetCurrentThreadId();

        [DllImport("kernel32.dll")]
        private static extern IntPtr GetModuleHandle(string name);

        private IntPtr _hookWindowPtr = IntPtr.Zero;

        public KeyboardHookLib() { }

        private static ProcessKeyHandle _clientMethod = null;

        public void InstallHook(ProcessKeyHandle clientMethod) {
            _clientMethod = clientMethod;
            if (_hHookValue==0) {
                _keyBoardHookProcedure = new HookHandle(GetHookProc);

                _hookWindowPtr = GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName);

                _hHookValue = SetWindowsHookEx(WH_KEYBOARD_LL,_keyBoardHookProcedure,_hookWindowPtr,0);

                if (_hHookValue==0) {
                    UninstallHook();
                }
            }
        }

        //取消钩子事件
        public void UninstallHook() {
            if (_hHookValue!=0) {
                bool ret = UnhookWindowsHookEx(_hHookValue);
                if (ret) _hHookValue = 0;
            }
        }

        //钩子事件内部调用,调用_clientMethod方法转发到客户端应用
        private static int GetHookProc(int nCode,int wParam,IntPtr IParam) {
            if (nCode>=0) {
                HookStruct hookStruct = (HookStruct)Marshal.PtrToStructure(IParam,typeof(HookStruct));
                if (_clientMethod != null) {
                    bool handle = false;
                    _clientMethod(hookStruct,out handle);
                    if (handle) {
                        return 1;
                    }
                }
            }
            return CallNextHookEx(_hHookValue,nCode,wParam,IParam);
        }
        
    }
}
